package com.iwhalecloud.bss.kite.cucc.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iwhalecloud.bss.kite.cart.common.util.KiteSessionUtil;
import com.iwhalecloud.bss.kite.client.api.inf.IInfKiteServiceLogService;
import com.iwhalecloud.bss.kite.client.dto.inf.InfKiteServiceLogDTO;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteDateUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.zsmart.core.http.HttpRequest;
import com.ztesoft.zsmart.core.http.HttpRequestGet;
import com.ztesoft.zsmart.core.http.HttpRequestPost;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Map;

/**
 * <Description> http接口调用 <br>
 *
 * @author huang.caibiao<br>
 * @version 1.0<br>
 * @taskId <br>
 * @date 2020-02-25 <br>
 * @since R9.0<br>
 * @see com.iwhalecloud.bss.kite.common.util <br>
 */
public class KiteHttpUtils {

    /**
     * post调用
     *
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String post(String url, Map<String, Object> paramMap) {
        InfKiteServiceLogDTO logDto = initLog(url, JSONObject.toJSONString(paramMap));
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {

            HttpPost post = new HttpPost(url);
            StringEntity postingString = new StringEntity(JSON.toJSONString(paramMap), "UTF-8");
            post.setEntity(postingString);
            post.setHeader("Content-type", "application/json");
            post.setHeader("Cookie", "SESSION=" + getSessionId());
            // TODO 账户列表查询暂时使用session 不能提交
            HttpResponse response = httpClient.execute(post);
            String respParam = EntityUtils.toString(response.getEntity());
            logDto.setOutXml(respParam);
            logDto.setTransactionId(getSessionId());
            return respParam;
        }
        catch (IOException e) {
            logDto.setOutXml(e.getMessage());
            ErrorConsts.SYSTEM_ERROR.throwOut(e);

        }
        finally {
            try {
                httpClient.close();
            }
            catch (IOException e) {
                ErrorConsts.SYSTEM_ERROR.throwOut(e);
            }
            addInfServiceLog(logDto);
        }
        return null;

    }
    /**
     * 上传文件
     * @param url
     * @param bytes
     * @param fileName
     * @return
     */
    public static String postByteHttpFile(String url, byte[] bytes, String fileName,Map request) {
        CloseableHttpClient buildSSLCloseableHttpClient = null;
        CloseableHttpResponse response = null;
        String encodeStr = "";
        InfKiteServiceLogDTO logDto = initLog(url, fileName);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
/*
            buildSSLCloseableHttpClient = buildSSLCloseableHttpClient();
*/
            HttpPost post = new HttpPost(url);
            // HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
            MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            builder.addBinaryBody("files", bytes, ContentType.MULTIPART_FORM_DATA, fileName);
            builder.addTextBody("userLogin", (String) request.get("userLogin"));
            builder.addTextBody("infoType", (String) request.get("infoType"));
            builder.addTextBody("subInfoType", (String) request.get("subInfoType"));
            HttpEntity entity = builder.build();
            post.setEntity(entity);
            // TODO 后续代码中需要去掉
            post.setHeader("Cookie", "SESSION=" + getSessionId());
            response =  httpClient.execute(post);
            /*   response = buildSSLCloseableHttpClient.execute(httpPost);*/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                encodeStr = EntityUtils.toString(response.getEntity());
            }
            logDto.setOutXml(JSONObject.toJSONString(response));
            logDto.setTransactionId(getSessionId());
        }
        catch (Exception e) {
            logDto.setOutXml(e.getMessage());
            ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
        }
        finally {
            try {
                if (buildSSLCloseableHttpClient != null) {
                    buildSSLCloseableHttpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            }
            catch (IOException e) {
                ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
            }
            addInfServiceLog(logDto);
        }
        return encodeStr;
    }
    /**
     * 上传文件
     * @param url
     * @param bytes
     * @param fileName
     * @return
     */
    public static String postByte(String url, byte[] bytes, String fileName) {
        CloseableHttpClient buildSSLCloseableHttpClient = null;
        CloseableHttpResponse response = null;
        String encodeStr = "";
        InfKiteServiceLogDTO logDto = initLog(url, fileName);
        try {
            buildSSLCloseableHttpClient = buildSSLCloseableHttpClient();
            HttpPost httpPost = new HttpPost(url);
            // HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
            MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            builder.addBinaryBody("file", bytes, ContentType.MULTIPART_FORM_DATA, fileName);
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            // TODO 后续代码中需要去掉
            httpPost.setHeader("Cookie", "SESSION=" + getSessionId());
            response = buildSSLCloseableHttpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                encodeStr = EntityUtils.toString(response.getEntity());
            }
            logDto.setOutXml(JSONObject.toJSONString(response));
            logDto.setTransactionId(getSessionId());
        }
        catch (Exception e) {
            logDto.setOutXml(e.getMessage());
            ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
        }
        finally {
            try {
                if (buildSSLCloseableHttpClient != null) {
                    buildSSLCloseableHttpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            }
            catch (IOException e) {
                ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
            }
            addInfServiceLog(logDto);
        }
        return encodeStr;
    }


    public static String getFileViewURL(String url, Map<String, Object> paramMap, Map<String, String> headerMap) {
        InfKiteServiceLogDTO logDto = initLog(url, JSONObject.toJSONString(paramMap));
        CloseableHttpClient httpclient = null;
        StringBuffer sb = new StringBuffer(url);
        if (KiteMapUtils.isNotEmpty(paramMap)) {
            sb.append("?");
            for (Map.Entry<String, Object> param : paramMap.entrySet()) {
              sb.append(param.getKey()).append("=").append(param.getValue()).append("&");
            }
            url = sb.subSequence(0, sb.length() - 1).toString();
        }
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            httpGet.addHeader("Cookie", "SESSION=" + getSessionId());
            httpclient = buildSSLCloseableHttpClient();
            response = httpclient.execute(httpGet);
            logDto.setOutXml(JSONObject.toJSONString(response));
            logDto.setTransactionId(getSessionId());
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                return null;
            }
            else {
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                return result;
            }
        }
        catch (Exception e) {
            ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                }
                catch (IOException e) {
                    ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
                }
            }
            if (httpclient != null) {
                try {
                    httpclient.close();
                }
                catch (IOException e) {
                    ErrorConsts.SYSTEM_ERROR.throwOut(e.getMessage());
                }
            }
            addInfServiceLog(logDto);
        }
        return null;
    }
    /**
     * ============忽略证书
     */
    private static CloseableHttpClient buildSSLCloseableHttpClient() throws Exception {
        @SuppressWarnings("deprecation")
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            // 信任所有
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        }).build();
        @SuppressWarnings("deprecation")
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[] {"TLSv1"}, null,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

    /**
     * post调用 有头部信息
     *
     * @param url
     * @param paramMap
     * @param headerMap
     * @return
     * @throws IOException
     */
    public static String post(String url, Map<String, Object> paramMap, Map<String, String> headerMap) {

        HttpRequest httpRequest = new HttpRequestPost();
        if (KiteMapUtils.isNotEmpty(headerMap)) {
            for (Map.Entry<String, String> header : headerMap.entrySet()) {
                ((HttpRequestPost) httpRequest).addHeader(header.getKey(), header.getValue());

            }
        }

        try {
            return httpRequest.execute(url, paramMap);
        }
        catch (IOException e) {
            ErrorConsts.SYSTEM_ERROR.throwOut(e);
        }
        return null;
    }

    /**
     * get调用 没有头部信息
     *
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String get(String url, Map<String, Object> paramMap) {
        return get(url, paramMap, null);
    }

    /**
     * get调用 有头部信息
     *
     * @param url
     * @param paramMap
     * @return
     * @throws IOException
     */
    public static String get(String url, Map<String, Object> paramMap, Map<String, String> headerMap) {
        String sessionId = getSessionId();
        InfKiteServiceLogDTO logDto = initLog(url, JSONObject.toJSONString(paramMap));
        HttpRequest httpRequest = new HttpRequestGet();
        if (KiteMapUtils.isNotEmpty(headerMap)) {
            for (Map.Entry<String, String> header : headerMap.entrySet()) {
                ((HttpRequestGet) httpRequest).addHeader(header.getKey(), header.getValue());
            }
        }
        try {
            ((HttpRequestGet) httpRequest).addHeader("Cookie", "SESSION=" + sessionId);
            String respParam = httpRequest.execute(url, paramMap);
            logDto.setOutXml(respParam);
            logDto.setTransactionId(sessionId);
            return respParam;
        }
        catch (IOException e) {
            logDto.setOutXml(e.getMessage());
            ErrorConsts.SYSTEM_ERROR.throwOut(e);
        }
        finally {
            addInfServiceLog(logDto);
        }
        return null;
    }

    private static InfKiteServiceLogDTO initLog(String svcCode, String reqParam) {
        InfKiteServiceLogDTO logDto = new InfKiteServiceLogDTO();
        logDto.setLogId(SeqUtils.getNext(TableConsts.InfKiteServiceLog));
        logDto.setSvcCode(svcCode);
        logDto.setAppKey("KITE");
        logDto.setReqTime(KiteDateUtils.dateToLocalDateTime(new Date()));
        logDto.setInXml(reqParam);
        return logDto;
    }

    private static void addInfServiceLog(InfKiteServiceLogDTO logDto) {
        logDto.setRspTime(KiteDateUtils.dateToLocalDateTime(new Date()));

        IInfKiteServiceLogService service = SpringUtil.getBean(IInfKiteServiceLogService.class);
        service.addInfKiteServiceLog(logDto);
    }

    private static String getSessionId() {
        return KiteSessionUtil.getLocalSessionId();
    }

}
